home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
c
/
spwno413.zip
/
SOURCE.ZIP
/
SWAP_EMS.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-11-16
|
11KB
|
390 lines
IFNDEF __TPINC
NAME swap_ems
TITLE SPAWNO EMS swapping code
PAGE 60,132
;-----------------------------------
; (c) Copyright 1990,1991 Ralf Brown All Rights Reserved
; This file may be redistributed as a part of the complete SPAWNO package,
; under its distribution conditions
;
; SPAWNO v4.00
; Overlaying spawnv()
;
; File: SWAP_EMS
;-----------------------------------
__BSS__ equ 1 ; yes, we are using uninitialized storage
INCLUDE RULES.ASI ; define the various standard macros
INCLUDE SPAWNO.INC
Header@ ; set up segment and group definitions
ENDIF ;ndef __TPINC
;-----------------------------------------------------------
; data with relocatable items
JSeg@
public@ __SPAWNO_FUNCS_EMS
__SPAWNO_FUNCS_EMS label byte
dw spawno_init_ems ; called to determine whether to swap to EMS
dw write_block_ems ; called to write out memory
dw spawno_swapdone_ems ; called when all memory written out
dw spawno_swapin_ems ; called when ready to read back memory
dw read_ems ; called to read back a section of memory
dw spawno_finish_ems ; called to clean up at very end of swap
dw $ems_overlay ; address of code to append to resident stub
dw ems_overlay_size ; total size of code to be appended
dw ems_overlay_res ; number of bytes which must stay resident
JSegEnd@
;-----------------------------------------------------------
; initialized data
DSeg@
EMM_name DB "EMMXXXX0"
IFNDEF RBcomm
PubSym@ __spawn_ems,<DB 1>,__CDECL__ ; are we allowed to swap to EMS?
ELSE
ExtSym@ __spawn_ems,BYTE,__CDECL__
ENDIF ;RBcomm
DSegEnd@
;----------------------------------------------------------------
; uninitialized data storage area
BSeg@
ems_page_num dw ? ; current page number for EMS handle
ems_page_offset dw ? ; offset (in para) withing page
ems_page_num$ dw ? ; page number after reading in PSP
ems_page_offset$ dw ? ; offset (in bytes) after reading in PSP
BSegEnd@
;----------------------------------------------------------------
CSeg@
;----------------------------------------------------------------
; section of code to append to the common code when using EMS for
; swapping
;
; on entry,
; DX = segment at which to start reloading memory
; CS = DS = segment of program's PSP
; AX, BX, CX, SI, DI, ES unpredictable
; at exit:
; SS:SP must be preserved, but all other registers can be destroyed
; The device-specific code is always entered at the very beginning and
; must exit either by falling off the end or by branching to "abort_offset"
; bytes prior to its beginning with DS=CS (the latter only if it detects
; an error from which it cannot recover).
;
$ems_overlay proc far
ems_reloc_factor equ (offset $ems_overlay - resident_addr)
ASSUME DS:NOTHING
mov es,dx ; ES <- seg at which to start loading
ASSUME ES:NOTHING
xor bx,bx ; start on logical page 0
mov dx,0 ; DX <- EMS handle (will be patched)
$ems_handle equ word ptr ($-2)
ems_reload_loop:
mov ax,4400h ; map logical page into physical page 0
int 67h
or ah,ah ; was "map" call successful?
jnz short ($ems_overlay - abort_offset) ; quit if not
mov ax,0 ; AX <- EMS page frame seg (will patch)
page_frame_seg equ word ptr ($-2)
mov ds,ax ; DS -> page frame
ASSUME DS:NOTHING
mov cx,2000h ; 16K bytes = 8K words
$ems_partial equ word ptr ($-2)
xor si,si ; source offset is 0
xor di,di ; dest offset is 0
rep movsw
jmp short copied_page ; flush prefetch queue
ems_overlay_res equ $ - $ems_overlay
;
; everything beyond this point may be overwritten by the child program, since
; the first read above will restore it back to memory
;
$ems_pages dw 0 ; number of pages, excluding partial last
; will be filled in before copy to PSP
copied_page:
inc bx ; go to next logical page
mov ax,es ; move 16K higher in memory
add ax,400h
mov es,ax
dec word ptr cs:($ems_pages - ems_reloc_factor)
jg ems_reload_loop ; if not yet last, go do another full page
mov word ptr cs:($ems_partial - ems_reloc_factor),0
$ems_partial_size equ word ptr ($-2)
jz ems_reload_loop ; loop one last time if count reached 0
;
; exit by falling out of this subroutine
;
$ems_overlay endp
ems_overlay_size equ $ - $ems_overlay
;----------------------------------------------------------------
; entry: AX = start segment within EMS page frame
; ES = conventional-memory transfer segment
; exit: DS, ES = source, destination of copy
; DX = new conventional-memory transfer address
;----------------------------------------------------------------
set_segment_read proc near
mov ds,ax ; AX = start segment in EMS page frame
ASSUME DS:NOTHING
mov dx,es
ret
set_segment_read endp
set_segment_write proc near
mov dx,es
mov ds,dx
mov es,ax ; AX = start segment in EMS page frame
ret
set_segment_write endp
;----------------------------------------------------------------
; enter: AX=starting segment
; BX = handle
; DX=num paras
; return: CF clear on success, set if failed
; AX, BX, CX, DX, ES destroyed
;----------------------------------------------------------------
read_ems proc near
ASSUME DS:DGROUP
mov cx,offset __TEXT:set_segment_read
jmp short transfer_EMS
read_ems endp
;----------------------------------------------------------------
; entry: AX = starting segment
; BX = handle
; DX = number of paragraphs
; return: CF clear on success, set if failed
; AX, BX, CX, DX, ES destroyed
;----------------------------------------------------------------
write_block_ems proc near
mov cx,offset __TEXT:set_segment_write
transfer_EMS:
push bp
mov bp,bx ; store handle
ASSUME DS:DGROUP
mov es,ax
ASSUME ES:NOTHING
push di
push si
xchg cx,dx
xfer_ems_loop:
push dx
mov ax,4400h ; map physical page 0
mov bx,ems_page_num
mov dx,bp ; DX <- handle
int 67h ; map in the appropriate EMS page
or ah,ah
jnz EMS_mapping_failed
mov bx,ems_page_offset
mov dx,bx
sub bx,400h ; 1024 paragraphs in a 16K EMS page
neg bx ; adjust for doing sub the wrong way
cmp bx,cx
jbe xfer_ems_fullpage
mov bx,cx
add ems_page_offset,bx
jmp short xfer_ems_do_it
xfer_ems_fullpage:
xor ax,ax
mov ems_page_offset,ax
inc ems_page_num
xfer_ems_do_it:
mov ax,page_frame_seg
add ax,dx
cmp ax,ax ; set ZF to indicate success
EMS_mapping_failed:
pop dx
jnz xfer_ems_failed
push ds
push dx
call dx ; set DS, ES, and DX
ASSUME DS:NOTHING,ES:NOTHING
xor si,si
xor di,di
push cx
mov cx,bx
shl cx,1
shl cx,1
shl cx,1 ; paragraphs to words
cld
rep movsw ; copy as much memory as we can
pop cx
add dx,bx
mov es,dx ; move higher in mem by amount copied
pop dx
pop ds
ASSUME DS:DGROUP
sub cx,bx ; update amount remaining
jnz xfer_ems_loop
clc ; tell caller we succeeded
xfer_ems_done:
pop si
pop di
pop bp
ret
xfer_ems_failed:
stc ; tell caller we failed
jmp xfer_ems_done
write_block_ems endp
;----------------------------------------------------------------
; return the number of EMS pages which are available (0 if no EMS) in AX
;
IFDEF RBcomm
public _EMS_available
ENDIF ;RBcomm
_EMS_available proc near
ASSUME DS:DGROUP
push es
push si
push di
mov ax,3567h
int 21h ; get vector for EMS driver
mov di,10 ; ES:DI -> driver name
mov si,offset DGROUP:EMM_name
mov cx,8 ; length EMM_name
cld
xor ax,ax ; assume no match
repz cmps EMM_name,byte ptr es:[di]
jnz EMS_avail_done
mov ah,42h
int 67h
or ah,ah ; was call successful?
mov ax,bx ; assume yes, return # of pages available
jz EMS_avail_done
xor ax,ax ; nope, so return zero
EMS_avail_done:
pop di
pop si
pop es
ret
_EMS_available endp
;----------------------------------------------------------------
; Determine whether able to swap to EMS, and prepare for swapping to EMS
; if able.
; on entry:
; AX = total number of paragraphs to swap out
; DX = number of paragraphs in PSP block to swap out
; return: CF set on error
; CF clear if able to swap
; AX = handle
;-----